import os
import ast
import socket
import socketserver
import datetime
from threading import Timer,Thread
from data.pool import ORDERPORT,PeerList,MAXDATANUM,MYNAME,ID,BlockNum,PoolData

client = {}
threads = {}
myPort = 11181
ORDER = []

class MyTCPHandler(socketserver.BaseRequestHandler):
    def setup(self):
        pass

    def handle(self):
        global client
        login = ''
        ip = ''
        try:
            while True:
                self.data = self.request.recv(MAXDATANUM)
                if not self.data:
                    break
                revData = self.data.decode('utf-8')
                if revData[0:4] == 'HBS:':
                    temp = revData.split(':')
                    if temp[1] != 'v0.1':
                        # 版本号错误
                        self.request.sendall('ERR:VER:v0.1'.encode('utf-8'))
                        break
                    if temp[2] in client:
                        # 已建立链接
                        self.request.sendall(('ERR:NAME:' + MYNAME).encode('utf-8'))
                        break
                    if temp[3] == 'ORDER':
                        ORDER.append(temp[2])
                    login = temp[2]
                    client[login] = self.request
                    ip = self.client_address[0] + ':' + str(self.client_address[1])
                    PeerList.append(ip)
                    self.request.sendall(('LDG:v0.1:' + MYNAME + ':' + ID).encode('utf-8'))
                else:
                    syncpool().analysis(self.data, self.request)
        except:
            pass
        finally:
            client.pop(login)
            PeerList.remove(ip)


class syncpool():
    global client
    global ORDERPORT
    global myPort
    def __init__(self):
        pass

    def startlink(self):
        # 建立与order的连接
        for s in ORDERPORT:
            if s[1] == myPort:
                continue
            self.startnewlink(s)

    def startnewlink(self, addr):
        # 新建连接
        tcp = socket.socket()
        try:
            tcp.bind(('127.0.0.1',myPort))
            tcp.connect(addr)
            mythread = reciveData(tcp)
            threads[addr] = mythread
            mythread.start()
            tcp.sendall(('HBS:v0.1:' + MYNAME + ":" + ID).encode('utf-8'))
        except:
            tcp.close()

    def sendData(self, msg, tcp):
        # 发送数据
        try:
            tcp.sendall(msg.encode('utf-8'))
        except:
            for key,value in enumerate(client):
                if value == tcp:
                    client.pop(key)
                    break

    def broadcast(self, data):
        # 广播新生的数据
        
        pass

    def getNewChain(self, startNum, endNum):
        # 获取新区块
        self.sendData('GKK:' + str(startNum) + ':' + str(endNum) + '结束序号', tcp)

    def getIPlist(self):
        # 获取IP列表
        self.sendData('GIP:' + str(myPort), tcp)
        tcp.sendall('GIP:' + str(myPort))

    def analysis(self, data, tcp):
        # 接收数据分析
        if len(data) < 4:
            return
        n = 4
        if data[:4] == 'LDG:':
            # 登录确认
            st = data.split(':')
            client[temp[2]] = tcp
            PeerList.append(tcp.getpeername()[0] + ':' + str(tcp.getpeername()[1]))
            self.sendData('GIP:' + str(myPort), tcp)
            return
        if data[:4] == 'GIP:':
            # 获取节点IP列表
            temp = ';'.join(PeerList)
            self.sendData('SIP:' + temp, tcp)
        if data[:4] == 'SIP:':
            # 连接节点IP列表
            if len(data) > 4:
                temp = data[4:].split(';')
                for i in temp:
                    t = temp.split(':')
                    self.startnewlink((t[0], int(t[1])))
            # 获取块高
            self.sendData('GHI:' + str(BlockNum), tcp)
        if data[:4] == 'GHI:':
            # 获得块高
            self.sendData('SHI:' + str(BlockNum), tcp)
        if data[:4] == 'SHI:':
            # 比较块高，判断是否要更新链
            if BlockNum < int(data[4:]):
                self.sendData('GSH:0:-1', tcp)
        if data[:4] == 'GSH:':
            # 各块的HASH
            st = data.split(':')
            if st[2] == '-1' or int(st[2]) > BlockNum:
                st = str(BlockNum)
            # 获取hash并发送
            self.sendData('SSH:开始序号:停止序号:hash;hash;hash', tcp)
            pass
        if data[4:] == 'SSH:':
            # 对比hash，以找到有哪些块不同，以获得新块，减少网络传送

            self.getNewChain(startNum, endNum)
        if data[4:] == 'GKK:':
            # 获取区块，将按序号依次传送块

            self.sendData('SKK:块序号:块总分割数:块分割编号:块内容', tcp)
        if data[4:] == 'SKK:':
            # 获得区块，写入文件，请求下一区块

            self.sendData('NKK:块序号:块分割编号', tcp)
        if data[4:] == 'NKK:':
            # 继续发送下一块
            self.sendData('SKK:块序号:块总分割数:块分割编号:块内容', tcp)        
        if data[4:] == 'RND:':
            # 收到广播的新数据,如是新数据，放入池中
            newData = ast.literal_eval(data[:4])
            if type(newData) == dict:
                for d in PoolData:
                    if d.time == newData.time:
                        if d.hash == newData.hash:
                            return
            PoolData.append(newData)
        

        
        

class reciveData (threading.Thread):
    def __init__(self, tcp):
        threading.Thread.__init__(self)
        self.isRun = True
        self.tcp = tcp

    def run(self):
        try:
            while self.isRun:
                data = self.tcp.recv(MAXDATANUM)
                if not data:
                    self.close()
                    break
                syncpool().analysis(data, self.tcp)
        except:
            pass

    def close(self):
        self.isRun = False
        tcp.close()
